var Sptofile = {
    id: "form-spotfile-upload",
    //文件上传请求地址
    listUrl: "",
    uploadUrl: "",
    //版本号
    version: "1.0.0",
    //文件上传业务
    business: "",
    //文件存储
    files: [],
    //文件上传成功结果集合信息
    results: [],
    //分片，默认大小为5M
    chunkSize: 5 * 1024 * 1024,
    //最大分片数，即单个文件大小最大5GB
    maxChunk: 1024,
    //最大上传队列
    maxQueue: 10,
    //允许上传文件配置
    allowConfig: {
        //文件后缀扩展名校验
        suffix: true,
        //允许文件后缀扩展名
        suffixs: "png, jpg, jpeg, gif, bmp, svg, xls, xlsx, csv, ppt, pptx, doc, docx, pdf, txt, wps, avi, mp4, mov, rmvb, 3gp, asf, ogg, mp3, rmvb, wav, wma, wmv",
        //文件媒体类型校验
        mime: false,
        //允许媒体类型
        mimes: "image/png, image/jpeg, image/gif, image/bmp, image/svg+xml, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/pdf, text/plain, application/vnd.ms-works, video/x-msvideo, video/mp4, video/quicktime, audio/x-pn-realaudio, video/3gpp, video/x-ms-asf, audio/ogg, audio/x-mpeg, audio/x-pn-realaudio, audio/x-wav, audio/x-ms-wma, audio/x-ms-wmv"
    },
    /**
     * 初始文件上传列表表格
     * @example
     * Sptofile.init({url : ctx + "spotfile/upload", business : "picture"});
     * Sptofile.init({url : ctx + "spotfile/upload", allowConfig : {suffix : true, suffixs : "png, jpg, jpeg"}});
     */
    init: function (_options) {
        if (_options) {
            $.extend(true, Sptofile, _options);
        }

        if ($("#" + Sptofile.id).length > 0) {
            var _data = Sptofile.files ? Sptofile.files : [];

            //加载table
            tableIns1 = table.render({
                elem: '#fileList',
                height: "full",
                cellMinWidth: 100,
                data: [],
                parseData: function (res) { //将原始数据解析成 table 组件所规定的数据
                    if (!CoreUtil.isEmpty(res.data)) {
                        for (let m = 0; m < res.data.length; m++) {
                            if (res.data[m].status == "0") {
                                res.data[m].status = "success";
                            }
                        }
                    }
                    return {
                        "code": res.code, //解析接口状态
                        "msg": res.msg, //解析提示文本
                        "count": CoreUtil.isEmpty(res.data) ? 0 : res.data.total, //解析数据长度
                        "data": CoreUtil.isEmpty(res.data) ? null : res.data.records //解析数据列表
                    }
                },
                cols: [
                    [
                        {type: 'checkbox'},
                        {field: 'fileId', title: '编码', align: "center"},
                        {field: 'fileName', title: '名称', align: "center"},
                        {
                            field: 'fileSize', title: '大小', align: "center", templet: function (d) {
                                let fileSize = Sptofile.formatSize(d.fileSize);
                                return fileSize;
                            }
                        },
                        {field: 'fileType', title: '类型', align: "center"},
                        {
                            field: 'status', title: '状态', align: "center", templet: function (d) {
                                let status = d.status;
                                if (status == "loading") {
                                    return "加载中";
                                } else if (status == "ready") {
                                    return "待上传";
                                } else if (status == "starting") {
                                    return "上传中";
                                } else if (status == "pausing") {
                                    return "暂停";
                                } else if (status == "success") {
                                    return "成功";
                                } else if (status == "error") {
                                    return "失败";
                                } else {
                                    return "未知异常";
                                }
                            }
                        },
                        {
                            field: 'progress', title: '进度', align: "center", templet: function (d) {
                                return d.progress || "0%";
                            }
                        },
                        {width: 300, toolbar: "#fileOperation", title: '操作', align: "center"}
                    ]
                ],
                toolbar: '#toolbar'
            });

            //表头工具
            table.on('toolbar(fileList)', function (obj) {
                switch (obj.event) {
                    case 'batchDeleted':
                        var checkStatus = table.checkStatus(obj.config.id);
                        var data = checkStatus.data;
                        if (data.length == 0) {
                            layer.msg("请选择要批量删除的列");
                        } else {
                            var ids = [];
                            $(data).each(function (index, item) {
                                ids.push(item.id);
                            });
                            tipDialog(ids);
                        }
                        break;
                    case 'add':
                        Sptofile.add();
                        break;
                }
            });

            table.on('tool(fileList)', function (obj) {
                switch (obj.event) {
                    case 'delete':
                        Sptofile.remove(obj.data.fileId);
                        break;
                    case 'start':
                        Sptofile.start(obj.data.fileId);
                        break;
                    case 'pause':
                        Sptofile.pause();
                        break;
                    case 'download':
                        Sptofile.download(obj.data.fileId);
                        break;
                }
            });

            CoreUtil.sendGet(Sptofile.listUrl, null, function (res) {
                let resFilesData = res.data;

                for (let m = 0; m < resFilesData.total; m++) {
                    Sptofile.files.unshift({
                        "id": resFilesData.records[m].fileId,
                        "name": resFilesData.records[m].originalName,
                        "size": resFilesData.records[m].fileSize,
                        "type": resFilesData.records[m].fileType,
                        "status": "success",
                        "progress": "100%"
                    });
                }
                Sptofile.refresh();
            });
        }
    },
    /**
     * 添加上传文件
     */
    add: function () {
        $('#' + Sptofile.id + ' input[type="file"]').click();
        $('#' + Sptofile.id + ' input[type="file"]').change(function (e) {
            var files = e.currentTarget.files;
            for (var k = 0; k < files.length; k++) {
                files[k].status = "loading"; //文件加载解析中
                if (Sptofile.allowableFileCheck(files[k])) {
                    Sptofile.cuteFile(files[k]); //文件分片
                } else {
                    break;
                }
            }
            Sptofile.reset();
        });
    },
    /**
     * 开始上传
     */
    start: function (id, success, error) {
        if (id) {
            var index = Sptofile.getFileIndexById(id);
            if (Sptofile.files[index].status != "starting" && Sptofile.files[index].status != "success") {
                Sptofile.files[index].status = "starting"; //开始上传
                upload(Sptofile.files[index], 0, success, error);
                Sptofile.refresh();
            }
        } else {
            var ids = Sptofile.getFileTableSelect();
            if (ids) {
                if (ids.length > Sptofile.maxQueue) {
                    $.modal.msgWarning("最多能同时上传" + Sptofile.maxQueue + "个文件");
                }
                var queue = ids.length > Sptofile.maxQueue ? Sptofile.maxQueue : ids.length;
                for (var i = 0; i < queue; i++) {
                    var index = Sptofile.getFileIndexById(ids[i]);
                    if (Sptofile.files[index].status != "starting" && Sptofile.files[index].status != "success") {
                        Sptofile.files[index].status = "starting"; //开始上传
                        upload(Sptofile.files[index], 0, success, error);
                    }
                }
                Sptofile.refresh();
            }
        }

        //分片上传
        function upload(file, index, success, error) {
            if (file.status != "starting") {
                Sptofile.refresh();
                return;
            }
            var blocks = file.blocks;
            if (!blocks || blocks.length <= 0 || index >= blocks.length) {
                Sptofile.refresh();
                return;
            }
            new Promise(function (resolve, reject) {
                if (blocks[index].id) {
                    resolve({
                        code: 0,
                        data: blocks[index].id,
                        msg: "读取二进制字符串成功"
                    });
                } else {
                    var reader = new FileReader();
                    reader.readAsBinaryString(blocks[index].blob);
                    reader.onload = function (event) {
                        var md5 = $.md5(event.target.result);
                        resolve({
                            code: 0,
                            data: md5,
                            msg: "读取二进制字符串成功"
                        });
                    }
                }
            }).then(function (res) {
                new Promise(function (resolve, reject) {
                    //加载中、暂停、错误、成功状态则停止上传
                    if (file.status == undefined || file.status == "" || file.status == "loading" || file.status == "pausing" || file.status == "error" || file.status == "success") {
                        Sptofile.refresh();
                        return new Promise();
                    } else {
                        var fileIndex = Sptofile.getFileIndexById(file.id);
                        blocks[index].id = res.data;
                        Sptofile.files[fileIndex].blocks[index] = blocks[index];
                        uploadChunk(blocks[index], resolve, reject);
                    }
                }).then(function (res) {
                    if (res && res.code == 0) { //分片上传成功
                        if (res.data && res.data.fileId && res.data.status && res.data.status == "0") {
                            index = blocks.length - 1;
                            finishCallbak(file.id, blocks.length, index, "success");
                            //分片全部上传结束
                            Sptofile.results.push(res.data);
                            //自定义成功回调函数
                            if (typeof success == "function") {
                                success(res);
                            }
                        } else {
                            index = res.data.chunk; //当前分片
                            finishCallbak(file.id, res.data.chunks, index);
                            index++;
                            upload(file, index); //继续轮询上传下一个分片
                        }
                    } else {
                        finishCallbak(file.id, blocks.length, index, "error");
                        //自定义失败回调函数
                        if (typeof error == "function") {
                            error(res);
                        }
                    }
                }, function (err) { //分片上传失败
                    finishCallbak(file.id, blocks.length, index, "error");
                    //自定义失败回调函数
                    if (typeof error == "function") {
                        error(err);
                    }
                });
            });
        }

        /**
         * 上传文件分片
         */
        function uploadChunk(block, resolve, reject) {

            var formData = new FormData();
            //分片信息
            formData.append('id', block.id);
            formData.append('chunk', block.chunk);
            formData.append('chunks', block.chunks);
            formData.append('start', block.start);
            formData.append('end', block.end);
            formData.append('file', block.blob);
            formData.append('tbbh', $("#tbbh").val());
            //文件信息
            formData.append('fileId', block.file.id);
            formData.append('fileName', block.file.name);
            formData.append('fileSize', block.file.size);
            formData.append('fileType', block.file.type);


            $.ajax({
                url: CoreUtil.getContext() + Sptofile.uploadUrl,
                headers: {
                    'authorization': CoreUtil.getData("access_token")
                },
                data: formData,
                type: 'post',
                processData: false, // 不处理数据
                contentType: false, // 不设置内容类型
                success: function (result) {
                    if (typeof resolve == 'function') {
                        resolve(result);
                    }
                },
                error: function (result) {
                    if (typeof reject == 'function') {
                        reject(result);
                    }
                }
            });
        }

        //文件上传进度
        function finishCallbak(id, length, index, status) {
            var fileIndex = Sptofile.getFileIndexById(id);
            var progress = (((1 / parseFloat(length)) * (parseInt(index) + 1)) * 100).toFixed(2) + "%";
            Sptofile.files[fileIndex].progress = progress;
            if (status) {
                Sptofile.files[fileIndex].status = status;
            }
            Sptofile.refresh();
        }

    },
    /**
     * 暂停上传
     */
    pause: function (id) {
        if (id) {
            var index = Sptofile.getFileIndexById(id);
            Sptofile.files[index].status = "pausing"; //暂停上传
            Sptofile.refresh();
        } else {
            var ids = Sptofile.getFileTableSelect();
            if (ids) {
                for (var i = 0; i < ids.length; i++) {
                    var index = Sptofile.getFileIndexById(ids[i]);
                    Sptofile.files[index].status = "pausing"; //暂停上传
                }
                Sptofile.refresh();
            }
        }
    },
    /**
     * 移除上传文件
     * id为空移除表格选中项，不为空则移除该项
     */
    remove: function (id) {
        if (id) {
            var fileIndex = Sptofile.getFileIndexById(id);
            layer.confirm("确定移除【" + Sptofile.files[fileIndex].name + "】文件吗", {
                btn: ['确定', '取消'],
                title: "提示"
            }, function (index) {
                CoreUtil.sendPost("/spotfile/delete", {
                    ids: id
                }, function (res) {
                    Sptofile.files.splice(fileIndex, 1);
                    Sptofile.refresh();
                    layer.close(index);
                });
            });
        } else {
            var ids = Sptofile.getFileTableSelect();
            if (ids) {
                $.modal.confirm("确定移除选中的" + ids.length + "个文件吗？", function () {
                    for (var i = 0; i < ids.length; i++) {
                        var index = Sptofile.getFileIndexById(ids[i]);
                        Sptofile.files.splice(index, 1);
                    }
                    Sptofile.refresh();
                });
            }
        }
    },
    /**
     * 单个文件分片上传，不建议使用超大文件
     * @param {file} file 文件实体
     * @param {success} success 上传成功回调函数
     * @param {error} error 上传失败回调函数
     */
    upload: function (file, success, error) {
        file.status = "loading"; //文件加载解析中
        if (Sptofile.allowableFileCheck(file)) {
            Sptofile.cuteFile(file); //文件分片
        }
        setTimeout(function () {
            Sptofile.start(file.id, success, error);
        }, 800);
    },
    /**
     * 刷新表格
     */
    refresh: function () {
        if ($("#" + Sptofile.id).length > 0) {
            let tempData = [];
            let tempFile;
            for (let m = 0; m < Sptofile.files.length; m++) {
                tempFile = Sptofile.files[m];
                tempData.push({
                    'fileId': tempFile.id,
                    'fileName': tempFile.name,
                    'fileSize': tempFile.size,
                    'fileType': tempFile.type,
                    'status': tempFile.status,
                    'progress': tempFile.progress
                });
            }
            table.reload("fileList", {
                data: tempData
            });
        }
    },

    /**
     * 下载文件
     */
    download: function (fileId) {
        window.open(CoreUtil.getContext() + '/spotfile/download/' + fileId);
    },
    /**
     * 重置fileinput
     */
    reset: function () {
        if ($("#" + Sptofile.id).length > 0) {
            document.getElementById(Sptofile.id).reset();
        }
    },
    /**
     * 负责将文件切片
     */
    cuteFile: function (file) {
        var pending = [],
            total = file.size,
            chunks = Sptofile.chunkSize ? Math.ceil(total / Sptofile.chunkSize) : 1,
            index = 0,
            start = 0,
            len,
            end,
            blob;

        if (chunks > Sptofile.maxChunk) {
            $.modal.msgWarning("单个文件最大限制不超过" + Sptofile.formatSize(Sptofile.maxChunk * Sptofile.chunkSize));
            Sptofile.refresh();
            Sptofile.reset();
            return;
        }

        new Promise(function (resolve, reject) {
            var blob = file.slice(0, Sptofile.chunkSize);
            var reader = new FileReader();
            reader.readAsBinaryString(blob);
            reader.onload = function (event) {
                var md5 = $.md5(event.target.result);
                resolve({
                    code: 0,
                    data: md5,
                    msg: "读取二进制字符串成功"
                });
            }
        }).then(function (res) {
            file.id = $.md5(res.data);
            var isExist = Sptofile.getFileIndexById(file.id);
            if (isExist == -1) {
                while (index < chunks) {
                    len = Math.min(Sptofile.chunkSize, total - start);
                    end = Sptofile.chunkSize ? (start + len) : total;
                    blob = file.slice(start, end);
                    pending.push({
                        file: file,
                        blob: blob,
                        start: start,
                        end: end,
                        total: total,
                        chunks: chunks,
                        chunk: index++
                    });
                    start += len;
                }
                file.blocks = pending.concat();
                file.status = "ready";
                Sptofile.files.unshift(file);
                Sptofile.refresh();
                Sptofile.reset();
            }
        });
    },
    /**
     * 根据文件id或者文件的索引号
     */
    getFileIndexById: function (id) {
        if (id) {
            let j = 0;
            for (; j < Sptofile.files.length; j++) {
                if (id == Sptofile.files[j].id) {
                    return j;
                }
            }
        }
        return -1;
    },
    /**
     * 获取选中的文件
     */
    getFileTableSelect: function () {
        var rows = $.common.isEmpty($.table._option.uniqueId) ? $.table.selectFirstColumns() : $.table.selectColumns($.table._option.uniqueId);
        if (rows.length == 0) {
            $.modal.alertWarning("请至少选择一条记录");
            return;
        }
        return rows;
    },
    /**
     * 允许上传文件检验
     */
    allowableFileCheck: function (file) {

        if (Sptofile.allowConfig.suffix == undefined && Sptofile.allowConfig.mime == undefined) {
            $.modal.alertWarning("文件上传参数配置错误");
            return false;
        }
        if (Sptofile.allowConfig.suffix == false && Sptofile.allowConfig.mime == false) {
            $.modal.alertWarning("文件上传参数配置错误");
            return false;
        }
        if (Sptofile.allowConfig.suffix == true && !Sptofile.allowConfig.suffixs) {
            $.modal.alertWarning("文件上传参数配置错误");
            return false;
        }
        if (Sptofile.allowConfig.mime == true && !Sptofile.allowConfig.mimes) {
            $.modal.alertWarning("文件上传参数配置错误");
            return false;
        }

        if (!file) {
            return false;
        }

        if (Sptofile.allowConfig.suffix && Sptofile.allowConfig.suffix == true) {
            var suffix = file.name.substring(file.name.lastIndexOf(".") + 1, file.name.length);
            if (Sptofile.allowConfig.suffixs && Sptofile.allowConfig.suffixs.indexOf(suffix) == -1) {
                $.modal.alertWarning("请选择正确的文件格式：" + Sptofile.allowConfig.suffixs);
                return false;
            }
        }
        if (Sptofile.allowConfig.mime && Sptofile.allowConfig.mime == true) {
            var mime = file.type;
            if (Sptofile.allowConfig.mimes && Sptofile.allowConfig.mimes.indexOf(mime) == -1) {
                $.modal.alertWarning("请选择正确的媒体类型：" + Sptofile.allowConfig.mimes);
                return false;
            }
        }
        return true;
    },
    /**
     * 格式化文件大小, 输出成带单位的字符串
     * @method formatSize
     * @param {Number} size 文件大小
     * @param {Number} [pointLength=2] 精确到的小数点数。
     * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.
     * @example
     * console.log( Base.formatSize( 100 ) );    // => 100B
     * console.log( Base.formatSize( 1024 ) );    // => 1.00K
     * console.log( Base.formatSize( 1024, 0 ) );    // => 1K
     * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M
     * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G
     * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB
     */
    formatSize: function (size, pointLength, units) {
        var unit;
        units = units || ['B', 'K', 'M', 'G', 'TB'];
        while ((unit = units.shift()) && size > 1024) {
            size = size / 1024;
        }
        return (unit === 'B' ? size : size.toFixed(pointLength || 2)) + unit;
    }
}
